using System;
using System.Data;
using BizElements.Core.ProviderComponents;

namespace BizElements.Core
{
	#region Documentation.
	/// <summary>
	/// Encapsulates a connection and transaction objects that can be shared among data-access tier objects.
	/// </summary>
	/// <example>
	/// The following example creates a ConnectionProvider and begins a transaction that deletes multiple rows 
	/// from Territories and Region tables.
	/// <code>
	/// public void DeleteRegionAndItsTerritories(int regionId)
	/// {
	///		// Create connection to Northwind catalog.
	///		Northwind.BizElements.Catalog northwindCatalog = new Northwind.BizElements.Catalog();
	///		IConnectionProvider conn = northwindCatalog.CreateConnectionProvider();
	/// 
	/// 	try
	/// 	{				
	/// 		// Open connection and begin transaction.
	/// 		conn.BeginTransaction();
	/// 
	/// 		// Territories that reference the specified region must be deleted first.
	/// 		TerritoriesMeta territories = new TerritoriesMeta();
	/// 		DeleteStatement deleteTerritories = new DeleteStatement(territories);
	/// 		deleteTerritories.Where.Add(PredicateFactory.Compare(territories.RegionID, "=", regionId));
	/// 		// Use the connection provider that has a pending transaction.
	/// 		deleteTerritories.ConnectionProvider = conn;
	/// 		deleteTerritories.Execute();
	/// 
	/// 		// Delete the specified region.
	/// 		RegionMeta regions = new RegionMeta();
	/// 		DeleteStatement deleteRegion = new DeleteStatement(regions);
	/// 		deleteRegion.Where.Add(PredicateFactory.Compare(regions.RegionID, "=", regionId));
	/// 		// Use the connection provider that has a pending transaction.
	/// 		deleteRegion.ConnectionProvider = conn;
	/// 		deleteRegion.Execute();
	/// 
	/// 		// All required rows have been deleted. Commit transaction.
	/// 		conn.CommitTransaction();				
	/// 	}
	/// 	catch
	/// 	{
	/// 		// En error occured. Rollback entire transaction - no rows will be deleted.
	/// 		conn.RollbackTransaction();
	/// 		throw;
	/// 	}
	/// 	finally
	/// 	{
	/// 		// Close conection and return it to the connection pool.
	/// 		// It is a good practice to explicitly close connection immediately after it is no longer required.
	/// 		conn.CloseConnection();
	/// 	}
	/// }
	/// </code>
	/// </example>
	#endregion
	public interface IConnectionProvider : IDisposable
	{
		#region Methods.

		/// <summary>
		/// Opens the connection object.
		/// Throws exception if it's already open.
		/// </summary>
		void OpenConnection();

		/// <summary>
		/// Starts a new ADO.NET transaction using the open connection object of this class.
		/// Opens the connection if it isn't already open. 
		/// No nesting allowed, throws exception if the transaction is already pending.
		/// </summary>
		/// <remarks>Uses default <see cref="IsolationLevel"/>.</remarks>
		void BeginTransaction();

		/// <summary>
		/// Starts a new ADO.NET transaction using the open connection object of this class.
		/// Opens the connection if it isn't already open. 
		/// No nesting allowed, throws exception if the transaction is already pending.
		/// </summary>
		/// <param name="isolationLevel">The transaction isolation level.</param>
		void BeginTransaction(IsolationLevel isolationLevel);

		/// <summary>
		/// Commits a pending transaction on the open connection object of this class.
		/// Throws exception if there is no pending transaction.
		/// </summary>
		void CommitTransaction();

		/// <summary>
		/// Rolls back a transaction from a pending state.
		/// Throws exception if there is no pending transaction.
		/// </summary>
		void RollbackTransaction();

		/// <summary>
		/// Closes the connection to the database. This is the preferred method of closing any open connection.
		/// </summary>
		/// <remarks>
		/// <para>The Close method rolls back any pending transactions. It then releases the connection 
		/// to the connection pool, or closes the connection if connection pooling is disabled. 
		/// It is a good practice to explicitly close connection immediately after it is no longer required.</para>
		/// <para>Does nothing if the connection has already been closed.</para>
		/// </remarks>
		void CloseConnection();

		#endregion

		#region Properties.

		/// <summary>
		/// Gets the DBMS type this provider is working with.
		/// </summary>
		DbmsType DBMS{get;}

		/// <summary>
		/// Gets the value which indicates whether there is a pending transaction.
		/// </summary>
		bool IsTransactionPending{get;}

		/// <summary>
		/// Gets the value which indicates whether the connection is open.
		/// </summary>
		bool IsOpen{get;}

		/// <summary>
		/// Gets the connection object.
		/// </summary>
		IDbConnection Connection{get;}

		/// <summary>
		/// Gets the transaction object.
		/// </summary>
		IDbTransaction Transaction{get;}

        /// <summary>
        /// Gets a value indicating whether the connection provider has been disposed of.
        /// </summary>
        bool IsDisposed { get; }

		#endregion
	}    
}